categories/[slug]/page.tsx - 分类详情页

categories/[slug]/page.tsx - 分类详情页

基本信息

属性
路径src/app/categories/[slug]/page.tsx
类型Next.js 动态路由页面 (Server Component)
功能显示特定分类下的提示词列表

功能描述

展示单个分类的详细信息,包括分类描述、提示词数量、订阅功能,以及该分类下的提示词列表。支持分页、排序和搜索。

导入依赖

import { Metadata } from "next";
import { notFound } from "next/navigation";
import Link from "next/link";
import { getTranslations } from "next-intl/server";
import { ArrowLeft } from "lucide-react";
import { auth } from "@/lib/auth";
import { db } from "@/lib/db";
import config from "@/../prompts.config";
import { Button } from "@/components/ui/button";
import { PromptList } from "@/components/prompts/prompt-list";
import { SubscribeButton } from "@/components/categories/subscribe-button";
import { CategoryFilters } from "@/components/categories/category-filters";
import { McpServerPopup } from "@/components/mcp/mcp-server-popup";

Props 接口

interface CategoryPageProps {
  params: Promise<{ slug: string }>;
  searchParams: Promise<{ page?: string; sort?: string; q?: string }>;
}
参数类型说明
params.slugstring分类的 URL slug
searchParams.pagestring分页页码
searchParams.sortstring排序方式
searchParams.qstring搜索关键词

常量

const PROMPTS_PER_PAGE = 30;

元数据生成

generateMetadata({ params })

{
  title: category.name,
  description: category.description || `Browse prompts in ${category.name}`
}

查询参数处理

参数默认值处理
page1Math.max(1, parseInt(...))
sort"newest"直接使用
q-可选搜索词

排序选项

选项值排序逻辑
oldestcreatedAt: "asc"
most_upvotedvotes._count: "desc"
most_contributorscontributors._count: "desc"
默认createdAt: "desc"

数据查询

分类查询

const category = await db.category.findUnique({
  where: { slug },
  include: {
    _count: {
      select: { prompts: true, subscribers: true }
    }
  }
});

订阅状态

const isSubscribed = session?.user
  ? await db.categorySubscription.findUnique({
      where: {
        userId_categoryId: {
          userId: session.user.id,
          categoryId: category.id
        }
      }
    })
  : null;

提示词查询条件

const whereClause = {
  categoryId: category.id,
  isPrivate: false,
  isUnlisted: false,
  deletedAt: null,
  ...(q && {
    OR: [
      { title: { contains: q, mode: "insensitive" } },
      { content: { contains: q, mode: "insensitive" } }
    ]
  })
};

UI 结构

Container
└── Header
    ├── Back Button → /categories
    ├── Title Row
    │   ├── Category Name
    │   ├── SubscribeButton (if logged in)
    │   └── Description
    ├── Stats Row
    │   ├── Prompt Count
    │   └── Subscriber Count
    └── Filters (desktop + mobile)
        ├── CategoryFilters
        └── McpServerPopup
└── PromptList
    └── prompts + pagination

响应式布局

断点过滤器位置
Desktop (md:)标题右侧
Mobile统计信息下方

翻译键值

键值用途
categories.allCategories返回按钮
categories.promptCount提示词数量
categories.subscriberCount订阅者数量

组件引用

组件用途
PromptList提示词列表 + 分页
SubscribeButton订阅/取消订阅
CategoryFilters排序筛选器
McpServerPopupMCP 服务器配置

路由

路径说明
/categories返回分类列表
/categories/${slug}当前页

MCP 集成

config.features.mcp !== false 时显示 MCP 服务器弹窗,预填充当前分类。

← 返回目录